package optymalizacjaSkladowania;

import java.util.List;
import skladowisko.Kontener;
import skladowisko.Miejsce;
import skladowisko.Pole;
import skladowisko.Skladowisko;
import skladowisko.Terminal;
import skladowisko.Warstwa;
import skladowisko.transport.TransportPrzychodzacy;
import skladowisko.utils.XStreamTerminalCreator;
import skladowisko.utils.XStreamTerminalSaver;

/**
 *
 * @author Krzysiek
 */
public class MojAnalitykSkladowania extends AnalitykSkladowania
{

    private StrategiaK1 strategiaK1 = new StrategiaK1Standard();
    private StrategiaK2 strategiaK2 = new StrategiaK2Standard();
    private int parametr_q = 20;

    private Terminal t2;

    public MojAnalitykSkladowania(Terminal terminal)
    {
        super(terminal);
    }

    public MojAnalitykSkladowania()
    {
    }

    @Override
    public PropozycjaPrzydzialow przydzielajMiejsca(TransportPrzychodzacy transport)
    {
        XStreamTerminalSaver saver = new XStreamTerminalSaver();
        XStreamTerminalCreator creator = new XStreamTerminalCreator();
        saver.zapisz(terminal, "mojAnalityk_terminalTmp.xml");
        t2 = creator.wczytajTerminal("mojAnalityk_terminalTmp.xml");

        PropozycjaPrzydzialow propozycja = new PropozycjaPrzydzialow(transport);

        ListaOptymalnosciPol listaOptymalnosci = tworzListeOptymalnosciPol();


        for (Kontener k : transport.getKontenery())
        {
            Miejsce skad = k.getMiejsce();
            skad.sciagnij();
            Miejsce planowaneMiejsce = znajdzOptymalneMiejsce(k, listaOptymalnosci, propozycja);
            Przydzial przydzial = new Przydzial(planowaneMiejsce, k);
            k.skladuj(skad);
            propozycja.addPrzydzial(przydzial);
        }

        return propozycja;
    }

    private Miejsce znajdzOptymalneMiejsce(Kontener k, ListaOptymalnosciPol listaPol, PropozycjaPrzydzialow przydzialy)
    {
        Miejsce propozycja = null;
        double wynik = Double.MAX_VALUE;

        for (int i = 0; i < parametr_q; i++)
        {
            OptymalnoscPola kandydat = listaPol.pobierzListe().get(i);

            if(kandydat.getPole().getZawartoscPola().isPelne())
            {
                listaPol.pobierzListe().remove(i);
                i--;
                continue;
            }

            //TODO sprawdzenie mozliwosci spelnienia kryteriow obowiazkowych
            double ocena = kandydat.getOptymalnosc() + strategiaK2.k2(kandydat.getPole(), k);
            kandydat.getPole().getZawartoscPola().sciagnijObiekt(k);
            if (ocena < wynik)
            {
                wynik = ocena;
                propozycja = kandydat.getPole().getZawartoscPola().getPierwszaWolnaWarstwa();
                //TODO trzeba zwracac warstwe a nie Pole!                
            }
        }
        //TODO
        Warstwa w = (Warstwa)propozycja;
        w.getPole().getZawartoscPola().polozObiekt(k);
        //propozycja.poloz(k);
        return propozycja;
    }

    private ListaOptymalnosciPol tworzListeOptymalnosciPol()
    {
        ListaOptymalnosciPol lista = new ListaOptymalnosciPol();

        List<Skladowisko> skladowiska = t2.getSkladowiska();
        for (Skladowisko s : skladowiska)
        {
            List<Pole> pola = s.getPola();

            double optymalnosc = 0;
            for (Pole p : pola)
            {
                optymalnosc = strategiaK1.k1(p);
                lista.dodajPole(new OptymalnoscPola(p, optymalnosc));
            }
        }

        return lista;
    }

    /**
     * @param strategiaK1 the strategiaK1 to set
     */
    public void setStrategiaK1(StrategiaK1 strategiaK1)
    {
        this.strategiaK1 = strategiaK1;
    }

    /**
     * @param strategiaK2 the strategiaK2 to set
     */
    public void setStrategiaK2(StrategiaK2 strategiaK2)
    {
        this.strategiaK2 = strategiaK2;
    }

    /**
     * @return the parametr_q
     */
    public int getParametr_q()
    {
        return parametr_q;
    }

    /**
     * @param parametr_q the parametr_q to set
     */
    public void setParametr_q(int parametr_q)
    {
        this.parametr_q = parametr_q;
    }
}
